﻿package com.hoopchina.weibo;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLDecoder;
import java.net.URLEncoder;
import java.security.MessageDigest;
import java.util.Iterator;
import java.util.Set;
import java.util.TreeSet;

import org.json.JSONException;
import org.json.JSONObject;

import android.os.Bundle;
import android.util.Log;
/**
 * 
 * @author neusoft
 *
 */
/**
 * 封装对人人的请求，如：显示登录界面、退出登录、请求 人人 APIs等。
 * 
 * @author yong.li@opi-corp.com
 */
public class Renren {

	private static final String SESSION_KEY_URL = "http://graph.renren.com/renren_api/session_key";
	 
    public static final String USER_FULL_FIELDS = "name,email_hash, sex,star,birthday,tinyurl,headurl,mainurl,hometown_location,hs_history,university_history,work_history,contact_info";
    
    public static final String USER_COMMON_FIELDS = "name,headurl";
    
    /**
     * 如果服务器redirect该地址，SDK会认为用户做了取消操作。
     */
    public static final String CANCEL_URI = "rrconnect://cancel";

    /**
     * 如果服务器redirect该地址，SDK会认为用户做了确认操作。
     */
    public static final String SUCCESS_URI = "rrconnect://success";

    /**
     * 人人登录和授权的地址
     */
    public static final String AUTHORIZE_URL = "https://graph.renren.com/oauth/authorize";

    /**
     * 接口支持的数据格式
     */
    public static final String RESPONSE_FORMAT_JSON = "json";

    /**
     * 接口支持的数据格式
     */
    public static final String RESPONSE_FORMAT_XML = "xml";
    public static final String WIDGET_CALLBACK_URI = "http://widget.renren.com/callback.html";
    private static final String RESTSERVER_URL = "http://api.renren.com/restserver.do";
    private String mSessionKey = null;
    private String mSessionSecret = null;

    private String apiKey = "8e209d1a415a4d9d8f825642eedfb9d1";

    private int	   mConnectionTimeout = 5000;
    private String mAccessToken;
    private String mUserName;
    private String mHeadUrl;
    public Renren( String url ) {
        Bundle values = parseUrl(url);
        mAccessToken = values.getString("access_token");
        exchangeSessionKey( mAccessToken );
    }

    public Renren() {
    }
    
    public String getHeadUrl()
    {
    	return mHeadUrl;
    }
    public String getName()
    {
    	return mUserName;
    }
    
    public String getAccessToken()
    {
        return mAccessToken;
    }
    
    public void setAccessToken( String accessToken )
    {
        mAccessToken = accessToken;
    	exchangeSessionKey( mAccessToken );        
    }
    
    public Bundle decodeUrl(String s) {
        Bundle params = new Bundle();
        if (s != null) {
            params.putString("url", s);
            String array[] = s.split("&");
            for (String parameter : array) {
                String v[] = parameter.split("=");
                if (v.length > 1) {
                    params.putString(v[0], URLDecoder.decode(v[1]));
                }
            }
        }
        return params;
    }
    
    public Bundle parseUrl(String url) {
        url = url.replace("rrconnect", "http");
        url = url.replace("#", "?");
        try {
            URL u = new URL(url);
            Bundle b = decodeUrl(u.getQuery());
            b.putAll(decodeUrl(u.getRef()));
            return b;
        } catch (MalformedURLException e) {
            return new Bundle();
        }
    }
    
    public boolean getUserInfo() throws WeiboException
    {
        Bundle params = new Bundle();
        params.putString("method", "users.getInfo");
        String fields = USER_COMMON_FIELDS;
        params.putString("fields", fields);
        String userInfo = "";
        try{
        	userInfo = requestJSON(params);
        if(userInfo.equals(""))
        {
        	return false;
        }
        }catch(WeiboException e)
        {
        	e.printStackTrace();
        	return false;
        }

        userInfo = userInfo.substring(userInfo.indexOf('[')+1, userInfo.indexOf(']'));
        try {
            JSONObject obj = new JSONObject(userInfo);
            mUserName = obj.getString("name");
            mHeadUrl = obj.getString("headurl");
        } catch (JSONException e) {
        	e.printStackTrace();
            return false;
        }
        return true;
    }

    public int updateStatus( String content )
    {
    	try
    	{
	        Bundle params = new Bundle();
	        params.putString("method", "status.set");
	        params.putString("status", content );
	        String res = requestJSON( params );
	        Log.i("RenRen","res="+res);
			try {
			    JSONObject root = new JSONObject( res );
			    return root.getInt( "result" );
			} catch (JSONException e) {
				e.printStackTrace();
			}
	        return 0;
    	} catch(Exception e)
    	{
    		e.printStackTrace();
    	}
    	return -1;
    }

    public int updateStatus( String content, byte[] photo)
    {
        long albumId = 431994435;
        String fileName = "pic1.jpg";
        try {
            uploadPhoto( albumId, photo, fileName, content, "json" );
            return 1;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return -1;
    }
    private String parseContentType(String fileName) {
        String contentType = "image/jpg";
        fileName = fileName.toLowerCase();
        if (fileName.endsWith(".jpg")) contentType = "image/jpg";
        else if (fileName.endsWith(".png")) contentType = "image/png";
        else if (fileName.endsWith(".jpeg")) contentType = "image/jpeg";
        else if (fileName.endsWith(".gif")) contentType = "image/gif";
        else if (fileName.endsWith(".bmp")) contentType = "image/bmp";
        else throw new RuntimeException("不支持的文件类型'" + fileName + "'(或没有文件扩展名)");
        return contentType;
    }
    
    public void uploadPhoto(final long albumId, final byte[] photo, final String fileName,
            final String description, final String format ) {
    	Bundle params = new Bundle();
    	params.putString("method", "photos.upload");
    	params.putString("aid", String.valueOf(albumId));
    	params.putString("caption", description);

    	String contentType = parseContentType(fileName);
    	params.putString("format", format);
    	if (isSessionKeyValid()) {
    		params.putString("session_key", mSessionKey);
    	}
    	this.prepareParams(params);
    	String resp = uploadFile(RESTSERVER_URL, params, "upload", fileName, contentType, photo);
    }
    private HttpURLConnection sendFormdata(String reqUrl, Bundle parameters,
            String fileParamName, String filename, String contentType, byte[] data) {
        HttpURLConnection urlConn = null;
        try {
            URL url = new URL(reqUrl);
            urlConn = (HttpURLConnection) url.openConnection();
            urlConn.setRequestMethod("POST");
            urlConn.setConnectTimeout(5000);// （单位：毫秒）jdk
            urlConn.setReadTimeout(5000);// （单位：毫秒）jdk 1.5换成这个,读操作超时
            urlConn.setDoOutput(true);

            urlConn.setRequestProperty("connection", "keep-alive");

            String boundary = "-----------------------------114975832116442893661388290519"; // 分隔符
            urlConn.setRequestProperty("Content-Type", "multipart/form-data; boundary=" + boundary);

            boundary = "--" + boundary;
            StringBuffer params = new StringBuffer();
            if (parameters != null) {
                for (Iterator<String> iter = parameters.keySet().iterator(); iter.hasNext();) {
                    String name = iter.next();
                    String value = parameters.getString(name);
                    params.append(boundary + "\r\n");
                    params.append("Content-Disposition: form-data; name=\"" + name + "\"\r\n\r\n");
                    // params.append(URLEncoder.encode(value, "UTF-8"));
                    params.append(value);
                    params.append("\r\n");
                }
            }

            StringBuilder sb = new StringBuilder();
            sb.append(boundary);
            sb.append("\r\n");
            sb.append("Content-Disposition: form-data; name=\"" + fileParamName + "\"; filename=\""
                    + filename + "\"\r\n");
            sb.append("Content-Type: " + contentType + "\r\n\r\n");
            byte[] fileDiv = sb.toString().getBytes();
            byte[] endData = ("\r\n" + boundary + "--\r\n").getBytes();
            byte[] ps = params.toString().getBytes();

            OutputStream os = urlConn.getOutputStream();
            os.write(ps);
            os.write(fileDiv);
            os.write(data);
            os.write(endData);

            os.flush();
            os.close();
        } catch (Exception e) {
            throw new RuntimeException(e.getMessage(), e);
        }
        return urlConn;
    }

    public String uploadFile(String reqUrl, Bundle parameters, String fileParamName,
            String filename, String contentType, byte[] data) {
        HttpURLConnection urlConn = null;
        try {
            urlConn = sendFormdata(reqUrl, parameters, fileParamName, filename, contentType, data);
            String responseContent = read(urlConn.getInputStream());
            Log.i("RenRen","responseContent="+responseContent);
            return responseContent.trim();
        } catch (Exception e) {
            throw new RuntimeException(e.getMessage(), e);
        } finally {
            if (urlConn != null) {
                urlConn.disconnect();
            }
        }
    }
    public boolean isSessionKeyValid() {
        return (mSessionKey != null && mSessionSecret != null);
    }
    
    private String requestJSON(Bundle parameters) throws WeiboException {
        parameters.putString("format", "json");
        if (isSessionKeyValid()) {
            parameters.putString("session_key", mSessionKey);
        }
        this.prepareParams(parameters);
        return openUrl(RESTSERVER_URL, "POST", parameters);
    }
    
    private void prepareParams(Bundle params) {
        params.putString("api_key", apiKey);
        params.putString("v", "1.0");
        params.putString("call_id", String.valueOf(System.currentTimeMillis()));
        params.putString("xn_ss", "1");//sessionSecret作为加密密钥

        StringBuffer sb = new StringBuffer();
        Set<String> keys = new TreeSet<String>(params.keySet());
        for (String key : keys) {
            sb.append(key);
            sb.append("=");
            sb.append(params.getString(key));
        }
        sb.append(this.mSessionSecret);
        params.putString("sig", md5(sb.toString()));
    }
    
    private void exchangeSessionKey(String accessToken) {
        if (accessToken == null || accessToken.length() < 1) {
            return;
        }
        Bundle params = new Bundle();
        params.putString("oauth_token", accessToken);
        String sessionKey = "";
        try{
        	sessionKey = openUrl(SESSION_KEY_URL, "POST", params);
        }catch(WeiboException e)
        {
        	e.printStackTrace();
        }
        try {
            JSONObject obj = new JSONObject(sessionKey);
            String error = obj.optString("error", null);
            if (error != null) {
            }
            mSessionKey = obj.getJSONObject("renren_token").getString("session_key");
            mSessionSecret = obj.getJSONObject("renren_token").getString("session_secret");
            long expires = obj.getJSONObject("renren_token").getLong("expires_in");
        } catch (JSONException e) {
            e.printStackTrace();
        }
    }
    
    public String encodeUrl(Bundle parameters) {
        if (parameters == null) {
            return "";
        }
        StringBuilder sb = new StringBuilder();
        boolean first = true;
        for (String key : parameters.keySet()) {
            if (first) {
                first = false;
            } else {
                sb.append("&");
            }
            sb.append(key + "=" + URLEncoder.encode(parameters.getString(key)));
            //sb.append(key + "=" + parameters.getString(key));
        }
        return sb.toString();
    }
    
    private String read(InputStream in) throws IOException {
        StringBuilder sb = new StringBuilder();
        BufferedReader r = new BufferedReader(new InputStreamReader(in), 1000);
        for (String line = r.readLine(); line != null; line = r.readLine()) {
            sb.append(line);
        }
        in.close();
        return sb.toString();
    }
    
    public String openUrl(String url, String method, Bundle params) throws WeiboException {
        if (method.equals("GET")) {
            url = url + "?" + encodeUrl(params);
        }
        String response = "";
        int responseCode = -1;
        try {
            HttpURLConnection conn = (HttpURLConnection) new URL(url).openConnection();
            conn.setConnectTimeout(mConnectionTimeout);
            conn.setRequestProperty("User-Agent", "Baidu News");
            if (!method.equals("GET")) {
                conn.setRequestMethod("POST");
                conn.setDoOutput(true);
                conn.getOutputStream().write(encodeUrl(params).getBytes("UTF-8"));
            }

            response = read(conn.getInputStream());
        } catch (Exception e) {
        	throw new WeiboException(e.getMessage());
        }
        return response;
    }
    
    public String md5(String string) {
        if (string == null || string.trim().length() < 1) {
            return null;
        }
        try {
            return getMD5(string.getBytes("UTF-8"));
        } catch (UnsupportedEncodingException e) {
            throw new RuntimeException(e.getMessage(), e);
        }
    }

    private String getMD5(byte[] source) {
        try {
            MessageDigest md5 = MessageDigest.getInstance("MD5");
            StringBuffer result = new StringBuffer();
            for (byte b : md5.digest(source)) {
                result.append(Integer.toHexString((b & 0xf0) >>> 4));
                result.append(Integer.toHexString(b & 0x0f));
            }
            return result.toString();
        } catch (Exception e) {
            throw new RuntimeException(e.getMessage(), e);
        }
    }
}
